import { Injectable } from '@nestjs/common'
import { JwtService } from '@nestjs/jwt'
import { HttpService } from '@nestjs/axios'
import * as bcrypt from 'bcrypt'
import { TokenResult } from './auth.interface'
import * as APP_CONFIG from '@app/app.config'
import { LoginProvider } from '@app/constants/thirdparty'
import { UserService } from '@app/modules/user/user.service'
import { User } from '@app/modules/user/user.model'

@Injectable()
export class AuthService {
  constructor(
    private readonly httpService: HttpService,
    private readonly jwtService: JwtService,
    private readonly userService: UserService,
  ) { }

  // 通过用户ID验证账号
  validateUserById(id: string): Promise<User | null> {
    return this.userService.findById(id)
  }

  // 验证本地账号
  async validateLocalUser(username: string, password: string): Promise<User | null> {
    // 验证本地用户是否存在
    if (!username || !password) {
      return null
    }
    // 查询用户
    const user = await this.userService.findByUsername(username)
    if (!user) {
      return null
    }

    // 验证密码
    const isValid = await bcrypt.compare(password, user.password || '')
    return isValid ? user : null
  }

  // 第三方登录
  async handleOAuthLogin(
    provider: LoginProvider,
    openid: string,
    unionid: string,
    profile: {
      access_token: string,
      refresh_token?: string
      expires_in?: number
      nickname?: string
      avatar?: string
    }
  ): Promise<TokenResult> {
    let user = await this.userService.findByOauth(provider, openid)
    if (!user) {
      user = await this.userService.createWithOAuth(
        provider,
        openid,
        unionid,
        profile
      )
    }
    return this.generateToken(user)
  }

  // 通过 authorizationCode 获取 access_token
  async getHuaweiAccessToken(code: string): Promise<{ access_token: string, expires_in: number, refresh_token: string, id_token: string }> {
    const client_id = APP_CONFIG.HUAWEI.CLIENT_ID
    const client_secret = APP_CONFIG.HUAWEI.CLIENT_SECRET
    const grant_type = 'authorization_code'
    const url = `https://oauth-login.cloud.huawei.com/oauth2/v3/token`
    const data = {
      client_id,
      client_secret,
      grant_type,
      code,
    }
    return new Promise((resolve, reject) => {
      this.httpService.axiosRef.post(url, data, {
        headers: {
          'Content-Type': 'application/x-www-form-urlencoded'
        }
      }).then(res => {
        resolve(res.data)
      })
      .catch(err => {
        reject(err)
      })
    })
  }

  // 通过access_token 获取用户信息
  async getHuaweiAccountInfo(access_token: string): Promise<{ nickname: string, avatar: string }> {
    const url = `https://account.cloud.huawei.com/rest.php?nsp_svc=GOpen.User.getInfo`
    const data = {
      access_token,
      getNickName: 1
    }
    return new Promise((resolve, reject) => {
      this.httpService.axiosRef.post(url, data, {
        headers: {
          'Content-Type': 'application/x-www-form-urlencoded'
        }
      }).then(res => {
        const { displayName, headPictureURL } = res.data
        resolve({
          nickname: displayName || '',
          avatar: headPictureURL || ''
        })
      })
      .catch(err => {
        reject(err)
      })
    })
  }

  // 生成Token凭证
  generateToken(user: User): TokenResult {
    return {
      access_token: this.jwtService.sign({ data: { _id: user._id } }),
      refresh_token: this.jwtService.sign({
          data: { _id: user._id }, },
        {
          secret: APP_CONFIG.AUTH.jwtSecret,
          expiresIn: APP_CONFIG.AUTH.refreshExpiresIn,
        }
    ),
      expires_in: APP_CONFIG.AUTH.expiresIn,
    }
  }
}
